package fr.bludwarf.skywarrior.global;

import fr.bludwarf.skywarrior.evenements.Commencer;
import fr.bludwarf.skywarrior.evenements.Evenement;
import fr.bludwarf.skywarrior.evenements.EvenementImpossible;
import fr.bludwarf.skywarrior.exceptions.ConstructionImpossibleException;
import fr.bludwarf.skywarrior.exceptions.EvenementInconnuOublieException;
import fr.bludwarf.skywarrior.ile.Progression;

public abstract class Etat<T extends Entite> {
	
	protected T _entite;
	
	protected EtatPere<?,?,?> _etatPere = null;
	
	/** La période qui précède cet état */
	Periode _periode = null;
	
	public Etat(final T entite, final EtatPere<?,?,?> etatPere) {
		_entite = entite;
		_etatPere = etatPere;
	}
	
	/**
	 * Recopie
	 * @param etat
	 */
	protected Etat(final Etat<T> etat) {
		this._entite = etat._entite;
		this._etatPere = etat._etatPere;
	}
	
	/**
	 * Recopie
	 * @param etat
	 */
	protected Etat(final Etat<T> etat, final EtatPere<?,?,?> etatPere) {
		this._entite = etat._entite;
		this._etatPere = etatPere;
	}

	public Temps getTemps() {
		return _etatPere.getTemps();
	}

	/**
	 * @return le prochain évènement qui arrivera
	 * @throws TimeFactorInconnu 
	 */
	public abstract Evenement prochainEvenement() throws Exception;
	
	/**
	 * Avance le temps d'un certains nombre de secondes.
	 * <b>Il ne doit surtout pas y avoir d'évènements pendant l'avance !</b>
	 * @param temps nombre de secondes à avancer
	 * @throws ConstructionImpossibleException 
	 * @throws EvenementInconnuOublieException 
	 * @since 14 nov. 2011
	 */
	// FIXME:  le temps devrait être uniquement sur le monde
	public abstract void avancer(final double temps) throws Exception;
	
	public double tempsEcouleDepuis(final Etat<?> etat)
	{
		return Temps.tempsEcoule(getTemps(), etat.getTemps());
	}
	
	public T getEntite()
	{
		return _entite;
	}
	
	public Monde getMonde()
	{
		return getEntite().getMonde();
	}
	
	public EtatPere<?, ?, ?> getEtatPere()
	{
		return _etatPere;
	}
	
	public abstract void execute(Evenement e) throws Exception;
}
